package com.hsy.crm.web.service.impl;

import com.hsy.crm.web.domain.cm.App;
import com.hsy.crm.web.domain.cm.PageResult;
import com.hsy.crm.web.domain.cm.Unified;
import com.hsy.crm.web.domain.entity.FinOtherOrder;
import com.hsy.crm.web.domain.entity.FinOtherOrderAccount;
import com.hsy.crm.web.domain.po.finOtherOrder.FinOtherOrderPagePo;
import com.hsy.crm.web.domain.po.finOtherOrder.FinOtherOrderPo;
import com.hsy.crm.web.domain.vo.finOtherOrder.FinOtherOrderInsertVo;
import com.hsy.crm.web.domain.vo.finOtherOrder.FinOtherOrderPageVo;
import com.hsy.crm.web.mapper.FinOtherOrderAccountMapper;
import com.hsy.crm.web.mapper.FinOtherOrderMapper;
import com.hsy.crm.web.service.base.BaseService;
import com.hsy.crm.web.service.base.DataInitService;
import com.hsy.crm.web.utils.UuidUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class FinOtherOrderService extends BaseService<FinOtherOrder> {

    @Autowired
    FinOtherOrderMapper finOtherOrderMapper;

    @Autowired
    FinOtherOrderAccountMapper finOtherOrderAccountMapper;

    @Autowired
    AccountService accountService;

    @Transactional
    public Unified<Integer> examine(FinOtherOrder order) {
        FinOtherOrder dbOrder = finOtherOrderMapper.selectByPrimaryKey(order);
        dbOrder.setCustomerId(order.getCustomerId());
        Unified<Integer> unified = this.updateStatus(dbOrder,App.Status.SH);
        return unified;
    }

    @Transactional
    public Unified<Integer> doInvalid(FinOtherOrder order) {
        FinOtherOrder dbOrder = finOtherOrderMapper.selectByPrimaryKey(order);
        dbOrder.setCustomerId(order.getCustomerId());
        Unified<Integer> unified = this.updateStatus(dbOrder,App.Status.BC);
        return unified;
    }

    @Transactional
    public Unified<FinOtherOrder> insertFinOtherOrder(FinOtherOrderInsertVo vo) {
        Unified<FinOtherOrder> unified = new Unified<>();

        FinOtherOrder order = vo.getOrder();
        order.setCustomerId(vo.getCustomerId());
        order.setLoginUserId(vo.getLoginUserId());
        order.setLoginCompanyId(vo.getLoginCompanyId());
        order.setCode(DataInitService.getOrderCode());
        order.setStatus(App.Status.BC);

        this.insert(order);

        this.insertAccounts(vo);

        if( vo.getSaveType() == App.SaveType.EXAMINE ){
            examine(order);
        }

        unified.setData(order);

        return unified;
    }

    @Transactional
    public Unified<FinOtherOrder> updateFinOtherOrder(FinOtherOrderInsertVo vo) {
        Unified<FinOtherOrder> unified = new Unified<>();

        FinOtherOrder order = vo.getOrder();
        order.setCustomerId(vo.getCustomerId());
        finOtherOrderMapper.updateByPrimaryKeySelective(order);

        this.deleteAccounts(vo.getOrder());
        this.insertAccounts(vo);

        if( vo.getSaveType() == App.SaveType.EXAMINE ){
            examine(order);
        }

        unified.setData(order);
        return unified;
    }

    @Transactional
    public Unified<Integer> deleteFinOtherOrder(FinOtherOrder finOtherOrder) {
        this.deleteAccounts(finOtherOrder);
        return Unified.newInstance(this.delete(finOtherOrder));
    }

    public PageResult<FinOtherOrderPagePo> page(FinOtherOrderPageVo finOtherOrderPageVo) {
        Page page = PageHelper.startPage(finOtherOrderPageVo.getPage(),finOtherOrderPageVo.getLimit());
        PageResult<FinOtherOrderPagePo> pageResult = new PageResult<>();
        pageResult.setRows(finOtherOrderMapper.page(finOtherOrderPageVo));
        pageResult.setTotal(page.getTotal());
        return pageResult;
    }

    public Unified<FinOtherOrderPo> getOrder(FinOtherOrder finOtherOrder) {
        Unified<FinOtherOrderPo> unified = new Unified<>();
        FinOtherOrderPo po = new FinOtherOrderPo();
        po.setOrder(finOtherOrderMapper.getOrder(finOtherOrder));
        po.setAccounts(finOtherOrderMapper.getAccounts(finOtherOrder));
        unified.setData(po);
        return unified;
    }

    private void deleteAccounts(FinOtherOrder order){
        FinOtherOrderAccount account = new FinOtherOrderAccount();
        account.setCustomerId(order.getCustomerId());
        account.setFinOtherOrderId(order.getId());
        finOtherOrderAccountMapper.delete(account);
    }

    private void insertAccounts(FinOtherOrderInsertVo vo){

        List<FinOtherOrderAccount> accounts = vo.getAccounts();
        for( FinOtherOrderAccount account : accounts ){
            account.setCustomerId(vo.getCustomerId());
            account.setFinOtherOrderId(vo.getOrder().getId());
            account.setId(UuidUtils.getUuid());
            finOtherOrderAccountMapper.insert(account);
        }

    }

    private Unified<Integer> updateStatus(FinOtherOrder order,int status){
        Unified<Integer> unified = new Unified<>();

        FinOtherOrder updateOrder = new FinOtherOrder();
        updateOrder.setId(order.getId());
        updateOrder.setCustomerId(order.getCustomerId());
        updateOrder.setStatus(status);
        finOtherOrderMapper.updateByPrimaryKeySelective(updateOrder);

        this.updateAccounts(order,status);

        return unified;
    }

    private void updateAccounts(FinOtherOrder order,int status){
        accountService.updateBalance(order.getCustomerId(),order.getAccountId(),order.getAccountPrice(),getDirection(order.getType(),status));
    }

    private int getDirection(int type,int status){
        if( type == App.BussType.IN ){
            if( status == App.Status.SH ){
                return App.Direction.ADD;
            }else if( status == App.Status.BC ){
                return App.Direction.SUB;
            }
        }else if(type == App.BussType.OUT){
            if( status == App.Status.SH ){
                return App.Direction.SUB;
            }else if( status == App.Status.BC ){
                return App.Direction.ADD;
            }
        }


        return -1;
    }

}
